__author__ = 'Pierre Moermans'

import unittest
import datetime
from datetime import date
import calendar
from django.utils.datastructures import SortedDict

def getCustomersForTemplate(customers):
    availableCustomers = SortedDict()
    for customer in customers:
        availableCustomers[customer.name] = customer.id
    return availableCustomers

def getContractsForTemplate(contracts):
    availableContracts = SortedDict()
    for contract in contracts:
        availableContracts[contract.name] = contract.id
    return availableContracts

def getTimesheetsForTemplate(timesheets):
    availableTimesheets = SortedDict()
    for timesheet in timesheets:
        availableTimesheets[timesheet.id] = timesheet.buildTimesheetName()
    return availableTimesheets

def getFirstDayOfMonth(monthAndYear):
    if len(monthAndYear) != 6:
        raise Exception(monthAndYear + ' is not a valid MMyyyy')

    month = int(monthAndYear[0:2])
    if month < 0 or month > 12:
        raise Exception(str(month) + ' is no a valid month')
    year = int(monthAndYear[2:])
    return date(year,month,1)

def getDaysInMonth(date_in_month):
    return calendar.monthrange(date_in_month.year,date_in_month.month)[1]

def getMonthsForTemplate(timesheets):
    availableMonthsAsValueText = SortedDict()
    for timesheet in timesheets:
        days = list(timesheet.day_set.all())
        text = str(days[0].date.month) + "/" + str(days[0].date.year)
        if len(text) < 7:
            text = '0' + text
        availableMonthsAsValueText.insert(0,timesheet.id,text)
    return availableMonthsAsValueText

def getMonthsBeforeAndAfterForTemplate(monthsBefore=2,monthsAfter=2, timesheet=None):
    availableMonths = []
    most_recent_date = datetime.datetime.now()

    if timesheet is not None:
        most_recent_date = datetime.datetime.combine(list(timesheet.day_set.all())[-1].date,datetime.time())

    # adding 1 month (see code after) to January 30 might give March 2
    # to avoid this, always make the day before 29
    if most_recent_date.day > 28:
        most_recent_date = most_recent_date - datetime.timedelta(days = 5)

    for i in range(monthsAfter,-monthsBefore,-1):
        if (most_recent_date.month+i) % 12 == 0:
            availableMonths += [(12-(most_recent_date.month+i)%12,most_recent_date.year+((most_recent_date.month + i)/12)-1)]
        else:
            availableMonths += [((most_recent_date.month+i)%12,most_recent_date.year+((most_recent_date.month + i)/12))]

    availableMonthsAsValueText = SortedDict()
    for month,year in availableMonths:
        value = str(month) + str(year)
        if len(value) < 6:
            value = '0' + value
        text = str(month) + "/" + str(year)
        if len(text) < 7:
            text = '0' + text
        availableMonthsAsValueText.insert(0,value,text)
        
    return availableMonthsAsValueText

class TestUtils(unittest.TestCase):

    def test_getFirstDayOfMonth(self):
        first_day = getFirstDayOfMonth('042012')
        self.assertEqual(2012,first_day.year)
        self.assertEqual(4,first_day.month)
        self.assertEqual(1,first_day.day)

    def test_getFirstDayOfMonth_invalid_month(self):
        try:
            first_day = getFirstDayOfMonth('132012')
            self.fail(msg='should have had an exception')
        except Exception:
            pass

    def test_getFirstDayOfMonth_month_NaN(self):
        try:
            first_day = getFirstDayOfMonth('AB2012')
            self.fail(msg='should have had an exception')
        except Exception:
            pass

    def test_getFirstDayOfMonth_year_NaN(self):
        try:
            first_day = getFirstDayOfMonth('13ABCD')
            self.fail(msg='should have had an exception')
        except Exception:
            pass

    def test_getDaysOfMonth(self):
        day = date(2012,03,05)
        self.assertEqual(31,getDaysInMonth(day))
        day = date(2012,06,05)
        self.assertEqual(30,getDaysInMonth(day))